
#import "MiscURICell.h"
#import <misckit/misckit.h>

//---------------------------------------------------------------------------------------

NXAtom W3URIPboardType=NULL;

//---------------------------------------------------------------------------------------
	@implementation MiscURICell:Cell
//---------------------------------------------------------------------------------------

/*" blah...
	
	When a double-click is detected the cell tries to open its URL with the
	help of some other application. This application must offer a service menu
	that accepts either WebStep URIs or Plain Ascii Text that is interpreted as
	a URL. The default value %URLService specifies the name of the service
	menu item of the application in question, eg. to use Netsurfer(TM) the value
	should be `Netsurfer/Open URL' If no value is found the cell tries to use
	OmniWeb(TM).
	
"*/

//---------------------------------------------------------------------------------------
	+ initialize
//---------------------------------------------------------------------------------------

/*" Stores the uniqued string 'WebStep Universal Resource Identifier 1.0' in the
	global variable #W3URIPboardType. "*/

	{
	W3URIPboardType=NXUniqueStringNoCopy("WebStep Universal Resource Identifier 1.0");
	return self;
	}
	

//---------------------------------------------------------------------------------------
	- init;
//---------------------------------------------------------------------------------------
	
/*" Initialises and returns the receiver, a new icon Cell instance (that is, its 
	type is NX_ICONCELL) with a NULL-URI. The icon is set to an
	NXImage with the name `URI' that should be located in an appropriate place.
	If it is not found, the Cell wont be initialised and %nil is returned. "*/
		
	{
	NXImage *uriTiff=[NXImage findImageNamed:"URI"];
	
	if(!uriTiff)
		return nil;
	[super init];
	[self setIcon:"URI"];
	return self;	
	}


//---------------------------------------------------------------------------------------
	- initURICell:(const char *)aURI;
//---------------------------------------------------------------------------------------

/*" Initialises and returns the receiver, a new icon Cell instance (that is, its
	type is NX_ICONCELL) with the specified URI. The icon is set to an
	NXImage with the name `URI' that should be located in an appropriate place.
	If it is not found, the Cell wont be initialised and %nil is returned. "*/

	{
	if(![self init])
		return nil;
	[self setURI:aURI];
	return self;
	}


//---------------------------------------------------------------------------------------
	- (void)setURI:(const char *)aURI;
//---------------------------------------------------------------------------------------
	
/*" Copies %aURI as the receiver's contents. "*/

	{
	if(uri)
		NXZoneFree([self zone],uri);
	uri=NXCopyStringBufferFromZone(aURI,[self zone]);
	}
	

//---------------------------------------------------------------------------------------
	- (const char *)uri;
//---------------------------------------------------------------------------------------

/*" Returns the URI that the Cell represents "*/

	{
	return uri;
	}	
	

//---------------------------------------------------------------------------------------
	+ (BOOL)prefersTrackingUntilMouseUp;
//---------------------------------------------------------------------------------------

/*" Since we want "our" cell to be dragged around everywhere we return #YES. "*/

	{
	return YES;
	}


//---------------------------------------------------------------------------------------
	- (BOOL)trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame ofView:aView
//---------------------------------------------------------------------------------------

/*" Intercepts the handling of mouse events at the lowest level possible
	because this Cell class needs acess to the event structure of the mouse down
	event.
	
	This method first changes the window's event mask to also reveive 
	#NX_MOUSEDRAGGED events and then waits for the next event. In case of
	an #NX_MOUSEDRAGGED event it places its URI on the drag pasteboard and calls 
	#dragImage:at:offset:event:pasteboard:source:slideBack message in its control
	view. In case of an #NX_MOUSEUP event with #click being 2 
	(that is, a double-click) it also places the URI on the drag pasteboard and
	then invokes the specifed service. "*/ 

	{
	Window		*window;
	int			oldMask;
	NXEvent		theMDEvent;
	NXPoint		p0={0,0},origin=cellFrame->origin;
	NXAtom		pbType[]={W3URIPboardType, NXAsciiPboardType, NULL};
	Pasteboard 	*pBoard=[Pasteboard newName:NXDragPboard];
	const char	*serviceName;

	if(uri==NULL)
		return NO;

	window=[aView window];
	theMDEvent=*theEvent;
	oldMask=[window addToEventMask:NX_MOUSEDRAGGEDMASK];
	theEvent=[NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
	[window setEventMask:oldMask];

	if(theEvent->type==NX_MOUSEDRAGGED)
		{
		[pBoard declareTypes:pbType num:2 owner:self];
		[pBoard writeType:W3URIPboardType data:uri length:strlen(uri)];
		[aView dragImage:[NXImage findImageNamed:[self icon]] at:&origin
		 	offset:&p0 event:&theMDEvent pasteboard:pBoard source:self slideBack:YES];
		}
	else if(theEvent->type==NX_MOUSEUP && theEvent->data.mouse.click==2)
		{
		[pBoard declareTypes:pbType num:2 owner:self];
		[pBoard writeType:W3URIPboardType data:uri length:strlen(uri)];
		serviceName=[NXApp defaultValue:"URLService"];
		if(!serviceName)
			serviceName="OmniWeb/Open URL";
		NXPerformService(serviceName,pBoard);		
		}

	return NO;
	}


//---------------------------------------------------------------------------------------
	- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag;
//---------------------------------------------------------------------------------------

/*" Always returns #NX_DragOperationCopy. "*/

	{
	return NX_DragOperationCopy;
	}
	

//---------------------------------------------------------------------------------------
	- pasteboard:sender provideData:(NXAtom)datatype;
//---------------------------------------------------------------------------------------

/*" Initially only the `WebStep Universal Resource Identifier' is placed on
	the pasteboard. If the receiver insists on getting the standard ASCII
	representation it is provided lazily through this method. "*/

	{
#if DEBUG
	fprintf(stderr,"%s: receiver preferes %s\n",[[self class] name],datatype);
#endif
	if(datatype!=NXAsciiPboardType || uri==NULL)
		return nil;
	[sender writeType:datatype data:uri length:strlen(uri)];
	return self;
	}

//---------------------------------------------------------------------------------------
	@end
//---------------------------------------------------------------------------------------


